
package com.example;

import com.android.videoeditor.service.ApiService;
import com.android.videoeditor.service.ApiServiceListener;
import com.example.utils.BitmapCache;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.videoeditor.MediaItem;
import android.media.videoeditor.MediaVideoItem;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import java.util.List;
import java.util.StringTokenizer;

public class VEThumbnailTestActivity extends Activity {
    private Button mLoadVideoButton;
    private Button mGetThumbnailButton;
    private EditText mVideoUriTextEdit;
    private Gallery mVideoThumbnailsGallery;
    private ProgressBar mProgressBar;
    private TextView mProgressTextView;
    private TextView mTimeTextView;
    private Spinner mThumbnailResulotionsSpinner;
    private Spinner mThumbnailNumsSpinner;
    private String mVideoFilePath;
    
    private final String TAG = "VEThumbnailTestActivity";
    private int mState;

    private static final int STATE_INIT = 0x01;
    private static final int STATE_REQ_VIDEO = 0x02;
    private static final int STATE_LOAD_VIDEO = 0x03;
    private static final int STATE_REQ_THUMBNAILS = 0x04;
    private static final int STATE_COMPLETE_THUMBNAILS = 0x05;

    private MediaVideoItem mMediaVideoItem;
    private Thread mThumbnailWorker;
    private Handler mHandler;
    private long mThumbnailStartTime;
    private BitmapCache mBitmapCache;
    private Bitmap mDefaultThumbnail;
    private ImageAdapter mImageAdapter;
    private int mThumbnailNums;
    private int mThumbnailWidth;
    private int mThumbnailHeight;

    private static final String RPOJECT_NAME = "test";
    private static final String RPOJECT_PATH = "/mnt/sdcard/test";
    private static final boolean TEST_GALLERY = true;

    private final ServiceListener mServiceListener = new ServiceListener();
    private Toast mToast = null;
    
    // for test
    private int testIndex;

    // for test
    private Bitmap testThumbnail;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mLoadVideoButton = (Button)findViewById(R.id.btn_load_video);
        mGetThumbnailButton = (Button)findViewById(R.id.btn_get_thumbnail);
        mVideoUriTextEdit = (EditText)findViewById(R.id.et_video_uri);
        mProgressBar = (ProgressBar)findViewById(R.id.pb_progress);
        mProgressTextView = (TextView)findViewById(R.id.tv_progress);
        mTimeTextView = (TextView)findViewById(R.id.tv_time);
        mVideoThumbnailsGallery = (Gallery)findViewById(R.id.gallery_thumbnails);
        mThumbnailResulotionsSpinner = (Spinner)findViewById(R.id.spn_resolutions);
        mThumbnailNumsSpinner = (Spinner)findViewById(R.id.spn_thumbnail_nums);
        mVideoFilePath = "";
        mState = STATE_INIT;
        mThumbnailNums = 10;
        mThumbnailWidth = 160;
        mThumbnailHeight = 120;
        mMediaVideoItem = null;
        mThumbnailWorker = null;
        mHandler = new Handler(Looper.getMainLooper());
        mThumbnailStartTime = 0;
        mBitmapCache = new BitmapCache();
        mDefaultThumbnail = BitmapFactory
                .decodeResource(getResources(), R.drawable.effects_generic);

        // for test start
        testIndex = 0;
        testThumbnail = BitmapFactory.decodeResource(getResources(), R.drawable.icon_3d);
        // for test end

        mLoadVideoButton.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
                if (mState != STATE_REQ_VIDEO && mState != STATE_REQ_THUMBNAILS) {
                    Intent intent = new Intent();
                    intent.setAction(Intent.ACTION_GET_CONTENT);
                    intent.setType("video/*");
                    startActivityForResult(intent, 0);
                    mState = STATE_REQ_VIDEO;
                }
            }
        });

        mGetThumbnailButton.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
                if (mState == STATE_LOAD_VIDEO || mState == STATE_COMPLETE_THUMBNAILS) {
                    mState = STATE_REQ_THUMBNAILS;
                    disableThumbnailAction();
                    updateThumbnailUIProperty();
                    requestThumbnails();

                } else {
                    if (TEST_GALLERY) {
                        // for test start
                        disableThumbnailAction();
                        if (testIndex < mThumbnailNums) {
                            Log.v(TAG, "add testImage at --> " + testIndex);
                            mBitmapCache.addBitmapToCache(Integer.toString(testIndex),
                                    testThumbnail);
                            mVideoThumbnailsGallery.setSelection(testIndex, true);
                            ((ImageView)mVideoThumbnailsGallery.getSelectedView())
                                    .setImageBitmap(testThumbnail);
                            udpateProgress(testIndex++);
                        } else {
                            testIndex = 0;
                            udpateProgress(-1);
                            mBitmapCache.clearCache();
                            mVideoThumbnailsGallery.removeAllViewsInLayout();
                            mVideoThumbnailsGallery.setSelection(0, true);
                        }
                        enableThumbnailAction();
                        // for test end
                    }
                }
            }
        });

        mThumbnailResulotionsSpinner
                .setOnItemSelectedListener(new Spinner.OnItemSelectedListener() {
                    @Override
                    public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
                        String resolution = parent.getItemAtPosition(pos).toString();
                        Log.v(TAG, "thumbnail resolution changed --> " + resolution);
                        updateThumbnailUIProperty();
                    }

                    @Override
                    public void onNothingSelected(AdapterView<?> arg0) {
                    }
                });

        mThumbnailNumsSpinner.setOnItemSelectedListener(new Spinner.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
                String nums = parent.getItemAtPosition(pos).toString();
                Log.v(TAG, "thumbnail nums changed --> " + nums);
                updateThumbnailUIProperty();
            }

            @Override
            public void onNothingSelected(AdapterView<?> arg0) {
            }
        });

        mImageAdapter = new ImageAdapter(this);
        mVideoThumbnailsGallery.setAdapter(mImageAdapter);

        updateThumbnailUIProperty();
        
        mToast = Toast.makeText(this, "", Toast.LENGTH_LONG);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mBitmapCache.clearCache();
        if (testThumbnail != null) {
            testThumbnail.recycle();
            testThumbnail = null;
        }
        ApiService.deleteProject(this, RPOJECT_PATH);
    }

    @Override
    protected void onPause() {
        super.onPause();
        ApiService.unregisterListener(mServiceListener);
    }

    @Override
    protected void onResume() {
        ApiService.registerListener(mServiceListener);
        super.onResume();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case 0:
                if (resultCode == RESULT_OK) {
                    Uri videoUri = data.getData();
                    if (videoUri.getScheme().equals("content")) {
                        String[] mediaColumns = {
                                MediaStore.Video.Media._ID, MediaStore.Video.Media.DATA
                        };
                        Cursor cursor = managedQuery(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
                                mediaColumns, "_ID=" + videoUri.getLastPathSegment(), null, null);
                        cursor.moveToFirst();
                        mVideoFilePath = cursor.getString(cursor
                                .getColumnIndexOrThrow(MediaStore.Video.Media.DATA));
                    } else if (videoUri.getScheme().equals("file")) {
                        mVideoFilePath = videoUri.getPath();
                    }
                    mVideoUriTextEdit.setText(mVideoFilePath);
                    Log.v(TAG, "mVideoFilePath --> " + mVideoFilePath);
                    if (mVideoFilePath.length() > 0)
                        mVideoUriTextEdit.setSelection(mVideoFilePath.length() - 1);
                    updateThumbnailUIProperty();
                    
                    ApiService.createVideoEditor(this, RPOJECT_PATH, RPOJECT_NAME, mVideoFilePath);
                    disableThumbnailAction();
                }
                mState = STATE_LOAD_VIDEO;
                break;
            default:
                break;
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    private void updateThumbnailUIProperty() {
        String nums = mThumbnailNumsSpinner.getSelectedItem().toString();
        mThumbnailNums = Integer.parseInt(nums);

        String resolution = mThumbnailResulotionsSpinner.getSelectedItem().toString();
        StringTokenizer st = new StringTokenizer(resolution, "x");
        mThumbnailWidth = Integer.parseInt(st.nextToken());
        mThumbnailHeight = Integer.parseInt(st.nextToken());

        mProgressBar.setMax(mThumbnailNums);
        udpateProgress(-1);
        udpateThumbnailTime(0);

        mBitmapCache.clearCache();
        mVideoThumbnailsGallery.removeAllViewsInLayout();
        mVideoThumbnailsGallery.setSelection(0, true);

        // to invoke getCount() method again
        mVideoThumbnailsGallery.setAdapter(mImageAdapter);

        mThumbnailStartTime = 0;

        // for test
        testIndex = 0;
    }

    private void enableThumbnailAction() {
        mLoadVideoButton.setEnabled(true);
        mVideoUriTextEdit.setEnabled(true);
        mGetThumbnailButton.setEnabled(true);
        mThumbnailNumsSpinner.setEnabled(true);
        mThumbnailResulotionsSpinner.setEnabled(true);
    }

    private void disableThumbnailAction() {
        mLoadVideoButton.setEnabled(false);
        mVideoUriTextEdit.setEnabled(false);
        mGetThumbnailButton.setEnabled(false);
        mThumbnailNumsSpinner.setEnabled(false);
        mThumbnailResulotionsSpinner.setEnabled(false);
    }

    private void requestThumbnails() {
//        mThumbnailWorker = new Thread() {
//            public void run() {
                if (mMediaVideoItem != null) {
                    Log.v(TAG, "requestThumbnail --> started");
                    int indices[] = new int[mThumbnailNums];
                    for (int i = 0; i < mThumbnailNums; i++) {
                        indices[i] = i;
                    }
                    mThumbnailStartTime = System.currentTimeMillis();
                    ApiService.getMediaItemThumbnails(VEThumbnailTestActivity.this, RPOJECT_PATH, 
                        mMediaVideoItem.getId(), mThumbnailWidth, mThumbnailHeight, 0, 
                        mMediaVideoItem.getDuration(), mThumbnailNums, 0, indices);
                    Log.v(TAG, "requestThumbnail --> finished");
                }
//            }
//        };
//        mThumbnailWorker.start();
    }

    private void updateThumbnail(final Bitmap bitmap, final int index) {
//        mHandler.post(new Runnable() {
//            public void run() {
                Log.v(TAG, "upateThumbnail --> index " + index);
                long diff = System.currentTimeMillis() - mThumbnailStartTime;
                udpateProgress(index);
                udpateThumbnailTime(diff);
                mBitmapCache.addBitmapToCache(Integer.toString(index), bitmap);
                mVideoThumbnailsGallery.setSelection(index, true);
                ((ImageView)mVideoThumbnailsGallery.getSelectedView()).setImageBitmap(bitmap);

                if (index == mThumbnailNums - 1) {
                    mState = STATE_COMPLETE_THUMBNAILS;
                    enableThumbnailAction();
                }
//            }
//        });
    }

    private void udpateProgress(int index) {
        String progressText = String.format("[%02d/%02d]", index + 1, mThumbnailNums);
        mProgressTextView.setText(progressText);
        mProgressBar.setProgress(index + 1);
        Log.v(TAG, "udpateProgress --> " + progressText);
    }

    private void udpateThumbnailTime(long msec) {
        int seconds = (int)(msec / 1000);
        int minutes = seconds / 60;
        seconds = seconds % 60;
        int miliseconds = (int)(msec % 1000);
        String timeText = String.format("%02d:%02d.%03d", minutes, seconds, miliseconds);
        mTimeTextView.setText(timeText);
        Log.v(TAG, "udpateThumbnailTime --> " + timeText);
    }

    public class ImageAdapter extends BaseAdapter {
        private Context mContext;

        private int mGalleryItemBackground;

        public ImageAdapter(Context context) {
            mContext = context;
            TypedArray a = obtainStyledAttributes(R.styleable.gallery);
            mGalleryItemBackground = a.getResourceId(
                    R.styleable.gallery_android_galleryItemBackground, 0);
            a.recycle();
        }

        @Override
        public int getCount() {
            return mThumbnailNums;
        }

        @Override
        public Object getItem(int position) {
            return position;
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            Log.v(TAG, "getView --> position " + position);

            ImageView imageView = (ImageView)convertView;

            if (imageView == null)
                imageView = (ImageView)new ImageView(mContext);

            Bitmap thumbnail = mBitmapCache.getBitmapFromCache(Integer.toString(position));
            if (thumbnail == null)
                thumbnail = mDefaultThumbnail;

            imageView.setImageBitmap(thumbnail);
            imageView.setScaleType(ImageView.ScaleType.FIT_XY);
            // imageView.setBackgroundResource(mGalleryItemBackground);
            imageView.setLayoutParams(new Gallery.LayoutParams(mThumbnailWidth, mThumbnailHeight));

            return imageView;
        }
    }
    
    private class ServiceListener extends ApiServiceListener {
        @Override
        public void onVideoEditorCreated(String projectPath, List<MediaItem> mediaItems,
                Exception exception) {
            showMessage("onVideoEditorCreated" + ((exception == null) ? "" : " --> ex:" + exception));
            mMediaVideoItem = null;
            if (exception == null) {
                mMediaVideoItem = (MediaVideoItem)mediaItems.get(0);
            }
            enableThumbnailAction();
        }

        @Override
        public void onVideoEditorAspectRatioSet(String projectPath, int aspectRatio,
                Exception exception) {
            showMessage("onVideoEditorAspectRatioSet");
        }

        @Override
        public void onVideoEditorExportProgress(String projectPath, String filename, int progress) {
            showMessage("onVideoEditorExportProgress " + progress + "%");
        }

        @Override
        public void onVideoEditorExportComplete(String projectPath, String filename,
                Exception exception, boolean cancelled) {
            showMessage("onVideoEditorExportComplete " + ((exception == null) ? "" : "--> ex:" + exception));
        }

        @Override
        public void onVideoEditorExportCanceled(String projectPath, String filename) {
            showMessage("onVideoEditorExportCanceled");
        }

        @Override
        public void onVideoEditorDeleted(String projectPath, Exception exception) {
            showMessage("onVideoEditorDeleted " + ((exception == null) ? "" : "--> ex:" + exception));
        }

        @Override
        public boolean onMediaItemThumbnail(String projectPath, String mediaItemId,
                Bitmap thumbnail, int index, int token, Exception exception) {
            showMessage("onMediaItemThumbnail " + ((exception == null) ? (index+1) + "/" + mThumbnailNums : "--> ex:" + exception)); 
            if (exception == null) {
                updateThumbnail(thumbnail, index);
                return true;
            } else {
                enableThumbnailAction();
            }
            
            return false;
        }
    }
    
    private void showMessage(String message) {
        Log.d(TAG, message);
        mToast.setText(message);
        mToast.show();
    }
}
